package com.myjpa.common.date;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * @author: yaoll
 * @date: 2020-09-04
 * @verison: 1.0
 */
public class DateUtils {

	public static final String PATTERN_yyyyMMddHHmmss = "yyyyMMddHHmmss";
	public static final String PATTERN_yyyyMMddHHmmss2 = "yyyy-MM-dd HH:mm:ss";
	public static final String PATTERN_yyyyMMdd = "yyyyMMdd";
	public static final String PATTERN_HHmmss = "HHmmss";
	public static final String PATTERN_HHmm = "HHmm";
	public static final String PATTERN_MM = "MM";
	public static final String PATTERN_yyyy = "yyyy";
	public static final String PATTERN_yyyyMM = "yyyyMM";

	public static Date add(Date now, int field, int amount) {
		Calendar c = Calendar.getInstance();
		c.setTime(now);
		c.add(field, amount);
		return c.getTime();
	}

	public static String format(Date date) {
		return format(date, PATTERN_yyyyMMddHHmmss);
	}

	public static Date parse(String date) {
		return parse(date, PATTERN_yyyyMMddHHmmss);
	}

	public static String format(Date date, String pattern) {
		DateFormat format = new SimpleDateFormat(pattern);
		return format.format(date);
	}

	public static Date parse(String date, String pattern) {
		DateFormat format = new SimpleDateFormat(pattern);
		try {
			return format.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
			throw new RuntimeException("pattern[" + pattern + "] and date[" + date + "] not match");
		}
	}

	/**
	 * 时间字符串转化成分钟数
	 *
	 * @param time yyyyMMddHHmmss or HHmmss
	 * @return
	 */
	public static int toInt(String time) {
		String temp = time;
		if (time.length() == 14) {
			temp = time.substring(8);
		}
		int minute = Integer.parseInt(temp.substring(0, 2)) * 60 + Integer.parseInt(temp.substring(2, 4));
		if (minute >= 1440) {
			minute = minute - 1440;
		}
		return minute;
	}

	/**
	 * 分钟数转化为时间字符串
	 *
	 * @param minite
	 * @return string HHmmss
	 */
	public static String toString(int minite) {
		int tmp = minite;
		if (tmp >= 1440) {
			tmp = tmp - 1440;
		}
		return String.format("%02d", tmp / 60) + String.format("%02d", tmp % 60) + "00";
	}

	/**
	 * 下一个服务定制时间点
	 *
	 * @param thisTime
	 * @param targetPeirod
	 * @return
	 */
	public static String nextTargetPoint(String thisTime, Integer targetPeirod) {
		int minute = toInt(thisTime);
		minute = minute - (minute % targetPeirod) + targetPeirod;
		return toString(minute);
	}

	public static String thisOrNextTargetPoint(String thisTime, Integer targetPeirod) {
		int minute = toInt(thisTime);
		if (minute % targetPeirod != 0) {
			minute = minute - (minute % targetPeirod) + targetPeirod;
		}
		return toString(minute);
	}

	public static String thisOrLastTargetPoint(String thisTime, Integer targetPeirod) {
		int minute = toInt(thisTime);
		minute = minute - (minute % targetPeirod);
		return toString(minute);
	}

	/**
	 * 计算begin和end之间的定制时间点
	 *
	 * @param begin  包含
	 * @param end    包含
	 * @param period 时间间隔,单位分钟
	 * @return
	 */
	public static List<String> getTimePoints(String begin, String end, int period) {
		return getTimePoints(begin, end, period, false);
	}

	/**
	 * 不支持跨天,计算begin和end之间的定制时间点
	 *
	 * @param begin
	 * @param end
	 * @param period
	 * @param containEnd 是否包含结束时间
	 * @return
	 */
	public static List<String> getTimePoints(String begin, String end, int period, boolean containEnd) {
		List<String> list = new LinkedList<>();
		int beginInt = toInt(begin);
		int endInt = toInt(end);
		int point = beginInt - (beginInt % period);
		while (true) {
			if ((containEnd && point <= endInt) || (!containEnd && point < endInt)) {
				list.add(toString(point));
				point += period;
			} else {
				break;
			}
		}
		return list;
	}

	/**
	 * 历史分精度数据时间点, 支持跨天
	 *
	 * @param begin  包含
	 * @param end    包含
	 * @param period
	 * @return
	 */
	public static List<String> getHisdataTimePoints(String begin, String end, int period) {
		SimpleDateFormat format = new SimpleDateFormat(DateUtils.PATTERN_yyyyMMddHHmmss);
		List<String> list = new LinkedList<>();
		String start = begin.substring(0, 8) + thisOrNextTargetPoint(begin, period);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(DateUtils.parse(start));
		while (true) {
			String tp = format.format(calendar.getTime());
			if (tp.compareTo(end) <= 0) {
				list.add(tp);
				calendar.add(Calendar.MINUTE, period);
			} else {
				break;
			}
		}
		return list;
	}

	/**
	 * 判断两个时间段是否是分隔开的(没有交叉重叠包含或覆盖)
	 *
	 * @param a1 HHmmss
	 * @param a2
	 * @param b1
	 * @param b2
	 * @return 注：该方法没有判断相等的情况，如：a1=b1 a2=b2 仍返回为true
	 */
	public static boolean isSeparate(String a1, String a2, String b1, String b2) {
		if (a1.compareTo(b1) < 0 && a2.compareTo(b1) > 0) {
			return false;
		}
		if (a1.compareTo(b2) < 0 && a2.compareTo(b2) > 0) {
			return false;
		}
		if (a1.compareTo(b1) < 0 && a2.compareTo(b2) > 0) {
			return false;
		}
		if (a1.compareTo(b1) > 0 && a2.compareTo(b2) < 0) {
			return false;
		}
		return true;
	}


	/**
	 * 判断两个时间段是否是包含或覆盖的
	 *
	 * @param a1
	 * @param a2
	 * @param b1
	 * @param b2
	 * @return
	 */
	public static boolean isNotSeparate(String a1, String a2, String b1, String b2) {
		if (a1.compareTo(b1) > 0 && a1.compareTo(b2) > 0) {
			return false;
		}
		if (a2.compareTo(b1) < 0 && a2.compareTo(b2) < 0) {
			return false;
		}
		return true;
	}

	/**
	 * date2比date1多的天数
	 *
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int differentDays(Date date1, Date date2) {
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);

		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		int day1 = cal1.get(Calendar.DAY_OF_YEAR);
		int day2 = cal2.get(Calendar.DAY_OF_YEAR);

		int year1 = cal1.get(Calendar.YEAR);
		int year2 = cal2.get(Calendar.YEAR);
		if (year1 != year2)   //同一年
		{
			int timeDistance = 0;
			for (int i = year1; i < year2; i++) {
				if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
				{
					timeDistance += 366;
				} else    //不是闰年
				{
					timeDistance += 365;
				}
			}

			return timeDistance + (day2 - day1);
		} else    //不同年
		{
			return day2 - day1;
		}
	}
}
